From de990614d702cb9202e39a22d0d3ddbba040441d Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 4 Apr 2018 12:38:09 +0200 Subject: [PATCH] inspector: Introduce so-called "overlays" Overlays are drawings that get rendered on top of the inspected window. The only overlay in existence so far is the highlight overlay, which is used to highlight widgets and replaces the "draw" signal handler used previously. --- gtk/inspector/highlightoverlay.c | 122 +++++++++++++++++++++++++++++++ gtk/inspector/highlightoverlay.h | 38 ++++++++++ gtk/inspector/inspect-button.c | 88 ++++------------------ gtk/inspector/inspectoroverlay.c | 71 ++++++++++++++++++ gtk/inspector/inspectoroverlay.h | 48 ++++++++++++ gtk/inspector/meson.build | 2 + gtk/inspector/size-groups.c | 15 +++- gtk/inspector/window.c | 41 +++++++++++ gtk/inspector/window.h | 13 +++- 9 files changed, 361 insertions(+), 77 deletions(-) create mode 100644 gtk/inspector/highlightoverlay.c create mode 100644 gtk/inspector/highlightoverlay.h create mode 100644 gtk/inspector/inspectoroverlay.c create mode 100644 gtk/inspector/inspectoroverlay.h diff --git a/gtk/inspector/highlightoverlay.c b/gtk/inspector/highlightoverlay.c new file mode 100644 index 0000000000..869262e148 --- /dev/null +++ b/gtk/inspector/highlightoverlay.c @@ -0,0 +1,122 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "highlightoverlay.h" + +#include "gtkintl.h" +#include "gtkwidget.h" + +struct _GtkHighlightOverlay +{ + GtkInspectorOverlay parent_instance; + + GtkWidget *widget; + GdkRGBA color; +}; + +struct _GtkHighlightOverlayClass +{ + GtkInspectorOverlayClass parent_class; +}; + +G_DEFINE_TYPE (GtkHighlightOverlay, gtk_highlight_overlay, GTK_TYPE_INSPECTOR_OVERLAY) + +static void +gtk_highlight_overlay_snapshot (GtkInspectorOverlay *overlay, + GtkSnapshot *snapshot, + GtkWidget *widget) +{ + GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (overlay); + graphene_rect_t bounds; + + if (!gtk_widget_compute_bounds (self->widget, widget, &bounds)) + return; + + gtk_snapshot_append_color (snapshot, + &self->color, + &bounds, + "InspectorHighlight"); +} + +static void +gtk_highlight_overlay_queue_draw (GtkInspectorOverlay *overlay) +{ + GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (overlay); + + gtk_widget_queue_draw (self->widget); +} + +static void +gtk_highlight_overlay_dispose (GObject *object) +{ + GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (object); + + g_clear_object (&self->widget); + + G_OBJECT_CLASS (gtk_highlight_overlay_parent_class)->dispose (object); +} + +static void +gtk_highlight_overlay_class_init (GtkHighlightOverlayClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkInspectorOverlayClass *overlay_class = GTK_INSPECTOR_OVERLAY_CLASS (klass); + + overlay_class->snapshot = gtk_highlight_overlay_snapshot; + overlay_class->queue_draw = gtk_highlight_overlay_queue_draw; + + gobject_class->dispose = gtk_highlight_overlay_dispose; +} + +static void +gtk_highlight_overlay_init (GtkHighlightOverlay *self) +{ + self->color = (GdkRGBA) { 0.0, 0.0, 1.0, 0.2 }; +} + +GtkInspectorOverlay * +gtk_highlight_overlay_new (GtkWidget *widget) +{ + GtkHighlightOverlay *self; + + self = g_object_new (GTK_TYPE_HIGHLIGHT_OVERLAY, NULL); + + self->widget = g_object_ref (widget); + + return GTK_INSPECTOR_OVERLAY (self); +} + +GtkWidget * +gtk_highlight_overlay_get_widget (GtkHighlightOverlay *self) +{ + return self->widget; +} + +void +gtk_highlight_overlay_set_color (GtkHighlightOverlay *self, + const GdkRGBA *color) +{ + if (gdk_rgba_equal (&self->color, color)) + return; + + self->color = *color; + gtk_inspector_overlay_queue_draw (GTK_INSPECTOR_OVERLAY (self)); +} diff --git a/gtk/inspector/highlightoverlay.h b/gtk/inspector/highlightoverlay.h new file mode 100644 index 0000000000..075e2e6234 --- /dev/null +++ b/gtk/inspector/highlightoverlay.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_HIGHLIGHT_OVERLAY_H__ +#define __GTK_HIGHLIGHT_OVERLAY_H__ + +#include "inspectoroverlay.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_HIGHLIGHT_OVERLAY (gtk_highlight_overlay_get_type ()) +G_DECLARE_FINAL_TYPE (GtkHighlightOverlay, gtk_highlight_overlay, GTK, HIGHLIGHT_OVERLAY, GtkInspectorOverlay) + +GtkInspectorOverlay * gtk_highlight_overlay_new (GtkWidget *widget); + +GtkWidget * gtk_highlight_overlay_get_widget (GtkHighlightOverlay *self); +void gtk_highlight_overlay_set_color (GtkHighlightOverlay *self, + const GdkRGBA *color); + +G_END_DECLS + +#endif /* __GTK_HIGHLIGHT_OVERLAY_H__ */ diff --git a/gtk/inspector/inspect-button.c b/gtk/inspector/inspect-button.c index 6f1efa1506..ce78c2a8ce 100644 --- a/gtk/inspector/inspect-button.c +++ b/gtk/inspector/inspect-button.c @@ -25,6 +25,8 @@ #include #include "window.h" + +#include "highlightoverlay.h" #include "object-tree.h" #include "gtkstack.h" @@ -124,19 +126,13 @@ find_widget_at_pointer (GdkDevice *device) return widget; } -static gboolean draw_flash (GtkWidget *widget, - cairo_t *cr, - GtkInspectorWindow *iw); - static void clear_flash (GtkInspectorWindow *iw) { - if (iw->flash_widget) + if (iw->flash_overlay) { - gtk_widget_queue_draw (iw->flash_widget); - g_signal_handlers_disconnect_by_func (iw->flash_widget, draw_flash, iw); - g_signal_handlers_disconnect_by_func (iw->flash_widget, clear_flash, iw); - iw->flash_widget = NULL; + gtk_inspector_window_remove_overlay (iw, iw->flash_overlay); + g_clear_object (&iw->flash_overlay); } } @@ -147,10 +143,8 @@ start_flash (GtkInspectorWindow *iw, clear_flash (iw); iw->flash_count = 1; - iw->flash_widget = widget; - g_signal_connect_after (widget, "draw", G_CALLBACK (draw_flash), iw); - g_signal_connect_swapped (widget, "unmap", G_CALLBACK (clear_flash), iw); - gtk_widget_queue_draw (widget); + iw->flash_overlay = gtk_highlight_overlay_new (widget); + gtk_inspector_window_add_overlay (iw, iw->flash_overlay); } static void @@ -206,7 +200,8 @@ on_highlight_widget (GtkWidget *button, return; } - if (iw->flash_widget == widget) + if (iw->flash_overlay && + gtk_highlight_overlay_get_widget (GTK_HIGHLIGHT_OVERLAY (iw->flash_overlay)) == widget) { /* Already selected */ return; @@ -332,56 +327,20 @@ gtk_inspector_on_inspect (GtkWidget *button, deemphasize_window (GTK_WIDGET (iw)); } -static gboolean -draw_flash (GtkWidget *widget, - cairo_t *cr, - GtkInspectorWindow *iw) -{ - GtkAllocation alloc; - - if (iw && iw->flash_count % 2 == 0) - return FALSE; - - if (GTK_IS_WINDOW (widget)) - { - GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); - /* We don't want to draw the drag highlight around the - * CSD window decorations - */ - if (child == NULL) - return FALSE; - - gtk_widget_get_allocation (child, &alloc); - } - else - { - alloc.x = 0; - alloc.y = 0; - alloc.width = gtk_widget_get_allocated_width (widget); - alloc.height = gtk_widget_get_allocated_height (widget); - } - - cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.2); - cairo_rectangle (cr, - alloc.x + 0.5, alloc.y + 0.5, - alloc.width - 1, alloc.height - 1); - cairo_fill (cr); - - return FALSE; -} - static gboolean on_flash_timeout (GtkInspectorWindow *iw) { - gtk_widget_queue_draw (iw->flash_widget); - iw->flash_count++; + gtk_highlight_overlay_set_color (GTK_HIGHLIGHT_OVERLAY (iw->flash_overlay), + &(GdkRGBA) { + 0.0, 0.0, 1.0, + (iw && iw->flash_count % 2 == 0) ? 0.0 : 0.2 + }); + if (iw->flash_count == 6) { - g_signal_handlers_disconnect_by_func (iw->flash_widget, draw_flash, iw); - g_signal_handlers_disconnect_by_func (iw->flash_widget, clear_flash, iw); - iw->flash_widget = NULL; + clear_flash (iw); iw->flash_cnx = 0; return G_SOURCE_REMOVE; @@ -407,21 +366,6 @@ gtk_inspector_flash_widget (GtkInspectorWindow *iw, iw->flash_cnx = g_timeout_add (150, (GSourceFunc) on_flash_timeout, iw); } -void -gtk_inspector_start_highlight (GtkWidget *widget) -{ - g_signal_connect_after (widget, "draw", G_CALLBACK (draw_flash), NULL); - gtk_widget_queue_draw (widget); -} - -void -gtk_inspector_stop_highlight (GtkWidget *widget) -{ - g_signal_handlers_disconnect_by_func (widget, draw_flash, NULL); - g_signal_handlers_disconnect_by_func (widget, clear_flash, NULL); - gtk_widget_queue_draw (widget); -} - void gtk_inspector_window_select_widget_under_pointer (GtkInspectorWindow *iw) { diff --git a/gtk/inspector/inspectoroverlay.c b/gtk/inspector/inspectoroverlay.c new file mode 100644 index 0000000000..a2e1c3d070 --- /dev/null +++ b/gtk/inspector/inspectoroverlay.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "inspectoroverlay.h" + +#include "gtkintl.h" + +typedef struct _GtkInspectorOverlayPrivate GtkInspectorOverlayPrivate; + +struct _GtkInspectorOverlayPrivate +{ +}; + +G_DEFINE_ABSTRACT_TYPE (GtkInspectorOverlay, gtk_inspector_overlay, G_TYPE_OBJECT) + +static void +gtk_inspector_overlay_default_snapshot (GtkInspectorOverlay *self, + GtkSnapshot *snapshot, + GtkWidget *widget) +{ +} + +static void +gtk_inspector_overlay_default_queue_draw (GtkInspectorOverlay *self) +{ +} + +static void +gtk_inspector_overlay_class_init (GtkInspectorOverlayClass *class) +{ + class->snapshot = gtk_inspector_overlay_default_snapshot; + class->queue_draw = gtk_inspector_overlay_default_queue_draw; +} + +static void +gtk_inspector_overlay_init (GtkInspectorOverlay *self) +{ +} + +void +gtk_inspector_overlay_snapshot (GtkInspectorOverlay *self, + GtkSnapshot *snapshot, + GtkWidget *widget) +{ + GTK_INSPECTOR_OVERLAY_GET_CLASS (self)->snapshot (self, snapshot, widget); +} + +void +gtk_inspector_overlay_queue_draw (GtkInspectorOverlay *self) +{ + GTK_INSPECTOR_OVERLAY_GET_CLASS (self)->queue_draw (self); +} + diff --git a/gtk/inspector/inspectoroverlay.h b/gtk/inspector/inspectoroverlay.h new file mode 100644 index 0000000000..867070b3c5 --- /dev/null +++ b/gtk/inspector/inspectoroverlay.h @@ -0,0 +1,48 @@ +/* + * Copyright © 2018 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_INSPECTOR_OVERLAY_H__ +#define __GTK_INSPECTOR_OVERLAY_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_INSPECTOR_OVERLAY (gtk_inspector_overlay_get_type ()) + +G_DECLARE_DERIVABLE_TYPE (GtkInspectorOverlay, gtk_inspector_overlay, GTK, INSPECTOR_OVERLAY, GObject) + +struct _GtkInspectorOverlayClass +{ + GObjectClass parent_class; + + void (* snapshot) (GtkInspectorOverlay *self, + GtkSnapshot *snapshot, + GtkWidget *widget); + void (* queue_draw) (GtkInspectorOverlay *self); +}; + +void gtk_inspector_overlay_snapshot (GtkInspectorOverlay *self, + GtkSnapshot *snapshot, + GtkWidget *widget); +void gtk_inspector_overlay_queue_draw (GtkInspectorOverlay *self); + +G_END_DECLS + +#endif /* __GTK_INSPECTOR_OVERLAY_H__ */ diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build index 5dd3a67647..7d8fedec78 100644 --- a/gtk/inspector/meson.build +++ b/gtk/inspector/meson.build @@ -11,8 +11,10 @@ inspector_sources = files( 'gtkstackcombo.c', 'gtktreemodelcssnode.c', 'gtktreemodelrendernode.c', + 'highlightoverlay.c', 'init.c', 'inspect-button.c', + 'inspectoroverlay.c', 'logs.c', 'magnifier.c', 'menu.c', diff --git a/gtk/inspector/size-groups.c b/gtk/inspector/size-groups.c index fdc4e4d1f2..b039eeeb59 100644 --- a/gtk/inspector/size-groups.c +++ b/gtk/inspector/size-groups.c @@ -19,6 +19,8 @@ #include #include "size-groups.h" + +#include "highlightoverlay.h" #include "window.h" #include "gtkcomboboxtext.h" @@ -32,6 +34,7 @@ typedef struct { GtkListBoxRow parent; + GtkInspectorOverlay *highlight; GtkWidget *widget; } SizeGroupRow; @@ -139,10 +142,18 @@ size_group_state_flags_changed (GtkWidget *widget, state = gtk_widget_get_state_flags (widget); if ((state & GTK_STATE_FLAG_PRELIGHT) != (old_state & GTK_STATE_FLAG_PRELIGHT)) { + GtkInspectorWindow *iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_toplevel (widget)); + if (state & GTK_STATE_FLAG_PRELIGHT) - gtk_inspector_start_highlight (row->widget); + { + row->highlight = gtk_highlight_overlay_new (row->widget); + gtk_inspector_window_add_overlay (iw, row->highlight); + } else - gtk_inspector_stop_highlight (row->widget); + { + gtk_inspector_window_remove_overlay (iw, row->highlight); + g_clear_object (&row->highlight); + } } } diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c index 428de723c6..13b0ff7b6c 100644 --- a/gtk/inspector/window.c +++ b/gtk/inspector/window.c @@ -355,6 +355,30 @@ gtk_inspector_window_new (void) NULL)); } +void +gtk_inspector_window_add_overlay (GtkInspectorWindow *iw, + GtkInspectorOverlay *overlay) +{ + iw->overlays = g_list_prepend (iw->overlays, g_object_ref (overlay)); + + gtk_inspector_overlay_queue_draw (overlay); +} + +void +gtk_inspector_window_remove_overlay (GtkInspectorWindow *iw, + GtkInspectorOverlay *overlay) +{ + GList *item; + + item = g_list_find (iw->overlays, overlay); + if (item == NULL) + return; + + gtk_inspector_overlay_queue_draw (overlay); + + iw->overlays = g_list_delete_link (iw->overlays, item); +} + void gtk_inspector_window_rescan (GtkWidget *widget) { @@ -393,6 +417,23 @@ gtk_inspector_prepare_render (GtkWidget *widget, region, node); + if (iw->overlays) + { + GtkSnapshot *snapshot; + GList *l; + + snapshot = gtk_snapshot_new (FALSE, "Inspector Overlay"); + gtk_snapshot_append_node (snapshot, node); + + for (l = iw->overlays; l; l = l->next) + { + gtk_inspector_overlay_snapshot (l->data, snapshot, widget); + } + + gsk_render_node_unref (node); + node = gtk_snapshot_free_to_node (snapshot); + } + return node; } diff --git a/gtk/inspector/window.h b/gtk/inspector/window.h index a9597b22bc..cc72aeecbf 100644 --- a/gtk/inspector/window.h +++ b/gtk/inspector/window.h @@ -26,6 +26,8 @@ #include +#include "inspectoroverlay.h" + #define GTK_TYPE_INSPECTOR_WINDOW (gtk_inspector_window_get_type()) #define GTK_INSPECTOR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_WINDOW, GtkInspectorWindow)) #define GTK_INSPECTOR_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_WINDOW, GtkInspectorWindowClass)) @@ -72,15 +74,17 @@ typedef struct GtkWidget *invisible; GtkWidget *selected_widget; - GtkWidget *flash_widget; GList *extra_pages; gboolean grabbed; + GtkInspectorOverlay *flash_overlay; gint flash_count; gint flash_cnx; + GList *overlays; + } GtkInspectorWindow; typedef struct @@ -96,12 +100,15 @@ GtkWidget *gtk_inspector_window_new (void); void gtk_inspector_flash_widget (GtkInspectorWindow *iw, GtkWidget *widget); -void gtk_inspector_start_highlight (GtkWidget *widget); -void gtk_inspector_stop_highlight (GtkWidget *widget); void gtk_inspector_on_inspect (GtkWidget *widget, GtkInspectorWindow *iw); +void gtk_inspector_window_add_overlay (GtkInspectorWindow *iw, + GtkInspectorOverlay *overlay); +void gtk_inspector_window_remove_overlay (GtkInspectorWindow *iw, + GtkInspectorOverlay *overlay); + void gtk_inspector_window_select_widget_under_pointer (GtkInspectorWindow *iw); void gtk_inspector_window_rescan (GtkWidget *iw); -- 2.30.2